package cn.daniellee.plugin.el;

import cn.daniellee.plugin.el.command.LimiterCommand;
import cn.daniellee.plugin.el.listener.BungeeListener;
import cn.daniellee.plugin.el.listener.PlayerListener;
import cn.daniellee.plugin.el.runnable.LimiterRunnable;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class EnterLimiter extends JavaPlugin {

	private static final String PACKAGE_VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];

	private static EnterLimiter instance;

	private String prefix;

	private File playerFile = new File(getDataFolder(), "player.yml");

	private FileConfiguration playerData = new YamlConfiguration();

	private boolean limited;

	private BukkitTask limiterTask;

	public static Map<String, Integer> availableSecond;

	@Override
	public void onEnable() {
		instance = this;

		getLogger().info(" ");
		getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> EnterLimiter Loaded <<<<<<<<<<<<<<<<<<<<<<<<");
		getLogger().info(">>>>> If you encounter any bugs, please contact author's QQ: 768318841 <<<<<");
		getLogger().info(" ");

		if (!Bukkit.spigot().getConfig().getBoolean("settings.bungeecord", false)) {
			getLogger().info(" ");
			getLogger().info(">>>>>>>>>>>> Bungeecord not detected, plugin disabled <<<<<<<<<<<<");
			getLogger().info(" ");
			Bukkit.getPluginManager().disablePlugin(this);
			return;
		}

		loadConfig();

		Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);

		Bukkit.getPluginCommand("enterlimiter").setExecutor(new LimiterCommand());

		this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
		this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new BungeeListener());
	}

	public void loadConfig() {
		getLogger().info("Loading config...");
		if(!getDataFolder().exists()) getDataFolder().mkdirs();
		// 载入插件基本配置
		prefix = "&7[&6" + getConfig().getString("prompt-prefix", "EnterLimiter") + "&7] &3: &r";
		limited = getConfig().getBoolean("setting.is-limited", false);
		if (limiterTask != null) limiterTask.cancel();
		if (limited) {
			limiterTask = new LimiterRunnable().runTaskTimerAsynchronously(this, 0, 20);
			try {
				if (!playerFile.exists()) playerFile.createNewFile();
				playerData.load(playerFile);
			} catch (Exception e) {
				e.printStackTrace();
				getLogger().info(" ");
				getLogger().info("An error occurred in player file load.");
				getLogger().info(" ");
			}
			if (availableSecond == null) availableSecond = new ConcurrentHashMap<>();
			// 载入玩家可用时间信息
			availableSecond.clear();
			Set<String> names = playerData.getKeys(false);
			for (String name : names) {
				int available = playerData.getInt(name + ".available", 0);
				if (available == 0) continue;
				availableSecond.put(name, available);
			}
		}
		saveDefaultConfig();
	}

	@Override
	public void onDisable() {
		// 插件卸载时保存还有时长的玩家
		if (availableSecond != null) {
			for (Map.Entry<String, Integer> entry : availableSecond.entrySet()) {
				playerData.set(entry.getKey() + ".available", entry.getValue());
			}
			savePlayerData();
		}

		if (limiterTask != null) limiterTask.cancel();

		this.getServer().getMessenger().unregisterOutgoingPluginChannel(this, "BungeeCord");
		this.getServer().getMessenger().unregisterIncomingPluginChannel(this, "BungeeCord");

		getLogger().info(" ");
		getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> EnterLimiter Unloaded <<<<<<<<<<<<<<<<<<<<<<<<");
		getLogger().info(" ");
	}

	public static EnterLimiter getInstance() {
		return instance;
	}

	public FileConfiguration getPlayerData() {
		return playerData;
	}

	public void savePlayerData() {
		try {
			playerData.save(playerFile);
		} catch (IOException e) {
			getLogger().info(" ");
			getLogger().info("An error occurred in player file save.");
			getLogger().info(" ");
			e.printStackTrace();
		}
	}

	public String getPrefix() {
		return prefix;
	}

	public boolean isLimited() {
		return limited;
	}

	public static Class<?> getNMSClass(String nmsClassName) throws ClassNotFoundException {
		return Class.forName("net.minecraft.server." + PACKAGE_VERSION + "." + nmsClassName);
	}
}
